#include "timer_task.hpp"
#include "any.hpp"
#include <unistd.h>
#include <regex>
#include <string>
#include <vector>

using namespace std;


class a {
public:
    a() {
        cout << "a created" << endl;
    }
    ~a() {
        cout << "a destroyed" << endl;
    }
};

void del_a(const a* p) {
    delete p;
}

void test_wheel() {
    time_wheel tw;
    a *aa = new a;
    tw.add_task(666, 3, bind(del_a, aa));
    for(int i = 0; i < 5; ++i) {
        tw.task_refresh(666);
        tw.tick();
        cout << "refresh ..." << endl;
        sleep(1);
    }
    tw.set_task_cancel(666);
    while(1) {
        cout << "tick....." << endl;
        tw.tick();
        sleep(1);
    }
}

void test_regex() {
    std::string str = "GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n";
    regex e("^(\\w+)\\s+(\\/[^\\s]+)\\s+(HTTP\\/[\\d\\.]+)(?:\n|\r\n)?$");
    
    std::smatch matches;

    bool ret = std::regex_match(str, matches, e);
    if (ret == false) {
        cout << "Error" << std::endl;
        return;
    }
    for (auto &s : matches) {
        std::cout << s << std::endl;
    }  
}

void test_regex_url() {
    //HTTP请求行格式：  GET /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n
    std::string str = "get /bitejiuyeke/login?user=xiaoming&pass=123123 HTTP/1.1\r\n";
    std::smatch matches;
    //请求方法的匹配  GET HEAD POST PUT DELETE ....
    std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.\\d)(?:\n|\r\n)?", std::regex::icase);
    //GET|HEAD|POST|PUT|DELETE   表示匹配并提取其中任意一个字符串
    //[^?]*     [^?]匹配非问号字符， 后边的*表示0次或多次
    //\\?(.*)   \\?  表示原始的？字符 (.*)表示提取?之后的任意字符0次或多次，知道遇到空格
    //HTTP/1\\.[01]  表示匹配以HTTP/1.开始，后边有个0或1的字符串
    //(?:\n|\r\n)?   （?: ...） 表示匹配某个格式字符串，但是不提取， 最后的？表示的是匹配前边的表达式0次或1次

    bool ret = std::regex_match(str, matches, e);
    if (ret == false) {
        return;
    }
    std::string method = matches[1];
    std::transform(method.begin(), method.end(), method.begin(), ::toupper);
    std::cout << method << std::endl;
    for (int i = 0; i < matches.size(); i++) {
        std::cout << i << " : ";
        std::cout << matches[i] << std::endl;
    }
    int *p = nullptr;
    delete p;
}

class Test{
    public:
        Test(int *pp) :p(pp)  {std::cout << "构造" << std::endl;}
        Test(const Test &t) {std::cout << "拷贝" << std::endl;}
        ~Test() {std::cout << "析构" << std::endl;cout << p << endl;delete p;}
    int *p;
};

void test_my_any() {
    int *p = new int;
    Test t(p);
    cout << "--------------------------------" << endl;
    {
        Any a;
        a = t;
    }
}

// class a{
// public:
//     a(int *v) : p(v) {}

//     a *clone1() {
//         return new a(*this);
//     }

//     a *clone2() {
//         return new a(p);
//     }
    
//     ~a() {
//         delete p;
//     }

//     int *p;

// };

#include <any>

void test_any() {
    // any a;
    // a = 10;
    // int *pi = any_cast<int>(&a) ;     
    // cout << *pi << endl;

    // a = string("hello");
    // string *ps = any_cast<string>(&a) ;
    // cout << *ps << endl;
}

#include "buffer.hpp"

void test_buf() {
    buffer buf;
    string data = "hello world\nhello C++\nhello Linux\n";
    buf.string_writer(data);
    string line = buf.find_line();
    while(!line.empty()) {
        cout << line << endl;
        line = buf.find_line();
    }
    for(int i = 0; i < 100; ++i) {
        buf.string_writer("hello world " + to_string(i) + "\n");
    }   
    cout << buf.get_readable_size() << endl;
    cout << "--------------------------------" << endl;

    buffer buf1 = buf.buffer_reader(buf.get_readable_size());
    cout << buf1.get_readable_size() << endl;
    cout << "--------------------------------" << endl;
    cout << buf.get_readable_size() << endl;
    cout << buf1.get_readable_size() << endl;
    cout << "--------------------------------" << endl;
    buf.buffer_writer(buf1);
    cout << buf.get_readable_size() << endl;
    cout << buf1.get_readable_size() << endl;
}

// #include "log_macro.hpp"

// void test_log() {
//     INFO_LOG("HRLLO");
//     DEBUG_LOG("%d %d", 1, 2);
// }

// #include "channel.hpp"

// void test_channel() {
//     channel channel(nullptr, 10);
//     cout << "test_channel" << endl;
// }

// #include "epoller.hpp"

// void test_epoller() {
//     epoller ep;
// }

#include <sys/eventfd.h>

void test_fd() {
    int fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (fd == -1) {
        perror("eventfd");
        return;
    }
    uint64_t val = 1;
    write(fd, &val, sizeof(val));
    write(fd, &val, sizeof(val));
    write(fd, &val, sizeof(val));
    uint64_t ret = 0;
    if(read(fd, &ret, sizeof(ret)) == sizeof(ret))
        cout << ret << endl;
    if(read(fd, &ret, sizeof(ret)) == sizeof(ret))
        cout << ret << endl;
    else {
        cout << "read fd error " << ret << endl;
    }
    close(fd);
}
template<class U>
void destroy(void *ptr) {
    delete (U*)ptr;
}

template<class T>
class smart_ptr {
public:
    smart_ptr(T *ptr) : _ptr(ptr) {
        cout << "smart_ptr(T *ptr)" << endl;
        destruct = destroy<T>;
    }
    template<class U>
    smart_ptr(U *p) : _ptr(p) {
        cout << "smart_ptr(U *p)" << endl;
        destruct = destroy<U>;
    }
    ~smart_ptr() {
        destruct(_ptr);
    }
    T *_ptr;
    void (*destruct)(void *);
};

 
class MyClass : public std::enable_shared_from_this<MyClass> {  
public:  
    std::shared_ptr<MyClass> getSharedPtr() {  
        return shared_from_this();  
    }  
  
    void print() {  
        std::cout << "MyClass instance\n";  
    }  
};  

void test_ptr() {
    //smart_ptr<A> p = new B;
    std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();  
    std::shared_ptr<MyClass> anotherPtr = ptr->getSharedPtr(); // 安全地获取另一个 shared_ptr  
    cout << ptr.use_count() << " " << anotherPtr.use_count() << endl;
    anotherPtr->print(); // 正常工作  
}

class A {

};
class B{
public:
    B()
        :a(getval()) 
    {}

    int getval() {
        return 0;
    }
    int a;
};

vector<string> split_str(const string &s, const string &sep) {
    vector<string> arr;
    for(size_t prev = 0, cur = s.find(sep, 0); true; prev = cur + sep.size(), cur = s.find(sep, prev)) {
        string sub = s.substr(prev, cur - prev);
        if(!sub.empty()) {
            arr.push_back(move(sub));
        }
        if(cur >= s.size()) {
            break;
        }
    }
    return arr;
}

void test_split() {
    string str = "hello,world,hello,,,c++,";
    vector<string> subs = split_str(str, ",");
    for(auto &s : subs) {
        cout << s << endl;
    }
}

#include <fstream>

void test_ifstream() {
    ifstream ifs("./log_macro.hpp", ios::binary);
    if(!ifs.is_open()) {
        cerr << "Cannot open" << endl;
        return;
    }
    ifs.seekg(0, ios::end);
    streamsize length = ifs.tellg();
    ifs.seekg(0, ios::beg);

    string s;
    s.resize(length);
    ifs.read((char*)s.c_str(), length);
    cout << s << endl;
    ifs.close();
}

void test_ofstream() {
    ofstream ofs("text.txt");
    if(!ofs.is_open()) {
        cerr << "Cannot open" << endl;
        return;
    }
    ofs.close();
}

string url_encode(const string &url, bool convert_space_to_plus) {
    string res;
    for (char c : url) {
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            res += c;
        } 
        else if(c == ' ' && convert_space_to_plus) {
            res += '+';
        }
        else {
            char temp[4] = {0};
            snprintf(temp, sizeof(temp), "%%%02X", c);
            res += temp;
        }
    }
    return res;
}

char hex_to_char(char c) {
    if(c >= '0' && c <= '9') {
        return c - '0';
    }
    else if(c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    }
    else if(c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    }
    return 0;
}
static string url_decode(const string &url, bool convert_plus_to_space) {
    string res;
    for (int i = 0; i < url.length(); ++i) {
        char c = url[i];
        if (c == '%') {
            if(i + 2 < url.length()) {
                char n1 = hex_to_char(url[++i]);
                char n2 = hex_to_char(url[++i]);
                res += (n1 << 4) + n2;
            }
            else {
                res += '%'; // 非法URL，解码出来的结果中会有%字符
                // ERR_LOG("invalid url: %s", url.c_str());
            }
        } 
        else if(c == '+' && convert_plus_to_space) {
            res +=' ';
        }
        else {
            res += c;
        }
    }
    return res;
}

void test_url() {
    string en = url_encode("/login?passwd=test&c  ", true);
    cout << en << endl;
    string de = url_decode(en, true);
    cout << de << endl;
}

bool is_valid_resource_path(const string &resource_path) {
    // 根据/对路径进行分割，然后判断路径深度
    // 初始化深度为0，若遇到..则--，否则++，若减到负数则说明跑到了网页根目录的上级目录去了，这是不合法的
    vector<string> dirs = split_str(resource_path, "/");
    int depth = 0;
    for(const auto &dir : dirs) {
        depth += dir == ".." ? -1 : 1;
        if(depth < 0) {
            return false;
        }
    }
    return true;
}

void test_path() {
    cout << is_valid_resource_path("/dir/../../index.html") << endl;
}

enum C {
    c
};

C get_enum() {
    C n = c;
    return n;
}

void test_enum() {
    C c = get_enum();
    cout  << c << endl;
}

int main() {
    // test_wheel();
    // test_regex();
    // test_regex_url();
    // test_my_any();
    // test_any();
    // test_buf();
    // test_log();
    // test_channel();
    // test_epoller();
    // test_fd();
    // test_ptr();
    //test_split();
    // test_ifstream();
    // test_ofstream();
    // test_url();
    // test_path();
    test_enum();
    return 0;
}